package com.bruce.demo2.patterns.demo1.creational.demo01.singleton.demo06;

/**
 * @PROJECT_NAME design_patterns
 * @DESCRIPTION 懒汉模式：双重检查锁模式+volatile  比较好的单例模式
 * 双重检查锁的实现方式，虽然解决了单例、性能、线程安全问题，但是在多线程的情况下可能出现空指针问题
 * 出现该问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作。
 * 解决方式：添加volatile关键字
 * volatile保证了不同线程对这个变量进行操作时的可见性，即一个线程修改了某个变量的值，这新值对其他线程来说是立即可见的
 * volatile禁止进行指令重排序 在volatile前边的语句只能在volatile变量之前执行，在volatile之后的语句也不能跑到volatile之前
 * <p>
 * 多线程执行保证安全的三要素：原子性、可见性、及有序性
 * 双重检查锁+volatile关键字是一种比较好的单例实现模式，能够保证多线程的情况下线程安全也不会有性能问题
 * @AUTHOR CNBruceLee
 * @DATE 2021/7/2 7:52
 */
public class Singleton {
    //1、构造函数私有化
    private Singleton() {
    }

    //2、定义 volatile关键字保证了多线程的可见性与防止重排序
    private static volatile Singleton instance;

    //3、对外提供访问方法
    public static Singleton getInstance() {
        //第一次判断如果instance不为null，不进入抢锁阶段，直接返回实例
        if (instance == null) {
            synchronized (Singleton.class) {
                //第二次判断 抢到锁之后再次判断是否为null
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

}
